package com.abo.yaas.domain;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

import com.abo.yaas.i18n.FieldTranslation;
import com.sun.xml.internal.txw2.annotation.XmlElement;

@SuppressWarnings("serial")
@Entity
@Table(name = "TBL_Auction")
@XmlRootElement
@XmlSeeAlso({ User.class, ItemLocation.class, ItemCondition.class })
public class Auction extends YaasPojo implements Serializable {

    @Version
    private Long version = 0l;

    private Date startTime = new Date();

    @FieldTranslation(tuid = "AUCTION_PREVIEW")
    private byte[] preview;

    @FieldTranslation(tuid = "AUCTION_TITLE")
    private String title = "";

    @FieldTranslation(tuid = "AUCTION_DESCRIPTION")
    private String description = "";

    @FieldTranslation(tuid = "AUCTION_END_DATE")
    private Date endTime;

    @FieldTranslation(tuid = "AUCTION_START_PRICE")
    private BigDecimal startPrice;

    @FieldTranslation(tuid = "AUCTION_MINIMUM_BID")
    private BigDecimal minimumBid;

    @FieldTranslation(tuid = "AUCTION_CATEGORY")
    private Category category;

    private User owner;

    private Bid leadingBid;

    private AuctionState state = AuctionState.AS_ACTIVE;

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof Auction)) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (getId() == null) {
            return super.equals(obj);
        }
        final Auction other = (Auction) obj;
        return getId().equals(other.getId())
                && version.equals(other.getVersion());
    }

    @ManyToOne
    @JoinColumn(name = "CategoryID", nullable = false)
    @XmlElementRef(name = "Category")
    public Category getCategory() {
        return category;
    }

    @Transient
    public String getCategoryTitle() {
        if (category != null) {
            return category.getTitle();
        }
        return null;
    }

    @Transient
    public BigDecimal getCurrentPrice() {
        return leadingBid == null ? getStartPrice() : leadingBid.getAmount();
    }

    @Column(name = "Description")
    @XmlElement
    public String getDescription() {
        return description;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "BeginDate")
    @XmlElement
    public Date getEndTime() {
        return endTime;
    }

    @OneToOne
    @JoinColumn(name = "LeadingBidId", nullable = true)
    @XmlElementRef(name = "WinningBid")
    public Bid getLeadingBid() {
        return leadingBid;
    }

    @Column(name = "MinimumBid")
    @XmlElement
    public BigDecimal getMinimumBid() {
        return minimumBid;
    }

    @ManyToOne
    @JoinColumn(name = "OwnerID", nullable = false)
    @XmlElementRef(name = "Owner")
    public User getOwner() {
        return owner;
    }

    @Transient
    public String getOwnerLogin() {
        return owner == null ? null : owner.getLogin();
    }

    @Transient
    public String getOwnerUserName() {
        if (owner == null) {
            return "";
        }
        return owner.getFullName();
    }

    @Transient
    public String getWinnerUserName() {
        if (leadingBid == null || leadingBid.getUserName() == null) {
            return "";
        }
        return leadingBid.getUserName();
    }
    
    @Column(name = "Preview")
    public byte[] getPreview() {
        return preview;
    }

    @Column(name = "StartPrice")
    @XmlElement
    public BigDecimal getStartPrice() {
        return startPrice;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "EndDate")
    @XmlElement
    public Date getStartTime() {
        return startTime;
    }

    @Enumerated(EnumType.ORDINAL)
    @Column(name = "StatusID", nullable = false)
    public AuctionState getState() {
        return state;
    }

    @Column(name = "Title")
    @XmlElement
    public String getTitle() {
        return title;
    }

    @Version
    @Column(name = "version", nullable = false, length = 5)
    public Long getVersion() {
        return version;
    }

    @Override
    public int hashCode() {
        int result = title.hashCode();
        result += 31 * description.hashCode();
        result += 31 * startTime.hashCode();
        result += 31 * owner.hashCode();
        result += 31 * category.hashCode();
        if (leadingBid != null) {
            result += 31 * leadingBid.hashCode();
        }
        return result;
    }

    public void resolve() {
        final Date currentDate = new Date();
        if (currentDate.after(startTime)) {
            setState(AuctionState.AS_RESOLVED);
        }
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public void setLeadingBid(Bid leadingBid) {
        this.leadingBid = leadingBid;
    }

    public void setMinimumBid(BigDecimal minimumBid) {
        this.minimumBid = minimumBid;
    }

    public void setOwner(User owner) {
        this.owner = owner;
    }

    public void setPreview(byte[] preview) {
        this.preview = preview;
    }

    public void setStartPrice(BigDecimal startPrice) {
        this.startPrice = startPrice;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public void setState(AuctionState state) {
        this.state = state;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setVersion(Long version) {
        this.version = version;
    }
}
